/***************************************************************/
//gameManager takes care of the turns, map, what's displaying, the menus, etc.
// Tyler Wozniak & Andrew Hall
/***************************************************************/


#include "GameManager.h"
using namespace std;

//Constructor. Will deal with anything necessary,
//then call initialize
GameManager::GameManager(void)
{
	mainDisp = new Display(*this);
	currMap = new Map();
	gameOver = false;
	gameWon = false;
	curTurn = 0;
	initialize();
}

//Returns the current player
Player* GameManager::getCurPlayer()
{
	return currentPlayer;
}

//Will initialize anything detailed like file I/O, etc
void GameManager::initialize( void )
{
	setCurState("title");
	playGame();
}

//Handles the game until completion
void GameManager::playGame()
{
	do 
	{
		//Output Stage
		mainDisp->drawCurrentScreen();
		//Input Stage
		char nextInput = ' ';
		while(!getNextInput(nextInput));
		//Processing Stage
		evaluateInput(nextInput);
	} while (!gameOver);
	mainDisp->printCredits();
}

GameManager::~GameManager(void)
{
	delete mainDisp;
	delete currMap;
	delete currentPlayer;
}

//Gets the next input and stores it to a reference passed in,
//And returns whether or not it's valid input
bool GameManager::getNextInput(char& nextIn)
{
	nextIn = _getch();
	vector<char> validVecs = getValidIns();
	int counts = count(validVecs.begin(),validVecs.end(),nextIn);
	return counts;
}

//Evauluates the input and does something useful based on which state the game is in
void GameManager::evaluateInput( char inp )
{
	switch(curState)
	{
	case TITLE: //Title screen
		if(inp == ' ')
		{
			setCurState("menu");
		}
		break;
	case MENU:	//Menu screen
		if(inp == 'q')
		{
			gameOver = true;
		}
		else if(inp == ' ')
		{
			currentPlayer = new Player(*this,mainDisp->getMenuOp());
			setCurState("game");
		}
		else
		{
			mainDisp->setMenuOp(inp);
		}
		break;
	case GAME: //Game screen
		if(inp == 'q')
		{
			gameOver = true;
		}
		if(inp == 'm')
		{
			setCurState("messages");
		}
		else
		{
			processGameTurn(inp);
		}
		break;
	case MESSAGES: //Messages screen
		if(inp == 'q')
		{
				setCurState("game");
		}
		break;
	default:
		break;
	}
}

//Returns the current map
Map* GameManager::getCurrentMap()
{
	return currMap;
}

//Returns the current display
Display* GameManager::getCurrentDisplay()
{
	return mainDisp;
}

//Sets the current screen to the screen we want to display
void GameManager::setCurState( string newState )
{
	//Lowercase dat string to avoid errors
	for(int i = 0; i < newState.length(); i++)
		newState[i] = tolower(newState[i]);
	//Now switch based on input...GRR switch statements dont work with strings...
	if(newState == "title")
		curState = TITLE;
	else if(newState == "menu")
		curState = MENU;
	else if(newState == "game")
		curState = GAME;
	else if(newState == "messages")
		curState = MESSAGES;
	else
		cout << "State \"" << newState << "\" does not exist" << endl;

}

//Returns a vector of valid input characters based on state
vector<char> GameManager::getValidIns()
{
	string inChars;
	switch(curState)
	{
	case TITLE: //Title screen
		inChars =" ";
		break;
	case MENU:	//Menu screen
		inChars ="ws ";
		break;
	case GAME: //Game screen
		inChars = "qmrtyfghvb ";
		break;
	case MESSAGES: //Messages screen
		inChars ="q";
		break;
	default:
		break;
	}
	vector<char> inVec;
	for(int i = 0; i < inChars.length();i++)
		inVec.push_back(inChars[i]);
	return inVec;
}

//Processes an actual turn within the game, allowing the player and enemies to attack
void GameManager::processGameTurn( char inp )
{
	vector<Unit*> enemiesAndPlayer = currMap->getNearbyEnemyPtrs(GameManager::AGGRO_RANGE,currentPlayer->getX(),currentPlayer->getY());
	enemiesAndPlayer.push_back(currentPlayer);
	//Now we have a vector of enemies and Players that need to process actions
	compareUnitEff speedComp;
	sort(enemiesAndPlayer.begin(),enemiesAndPlayer.end(),speedComp);
	//Sort based on their speeds so fastest go first!
	for(int i = 0; i < enemiesAndPlayer.size(); i++)
	{
		if(*(enemiesAndPlayer[i]) == (*currentPlayer)) //So if it's a player, we just do the action
		{
			currentPlayer->move(inp);
		}
		else // Otherwise, do the enemy action
		{
			static_cast<Enemy*>(enemiesAndPlayer[i])->evaluateAI(this);
		}
	}
	curTurn++; //Incrememnt the turn
	if(currentPlayer->currentHealth() < 1) //Check lose condition
	{
		gameOver = true;
		gameWon = false;
	}
	if(currMap->noMoreEnemies()) //Check win condition
	{
		gameOver = true;
		gameWon = true;
	}

	if(curTurn % 3 == 0) // regen every third turn
	{
		currentPlayer->regen();
	} 
}

